package com.caigou.task;

import com.caigou.bean.cms.entity.*;
import com.caigou.bean.vo.EsArticleMqVO;
import com.caigou.bean.vo.KeyValueVO;
import com.caigou.component.HtmlDetailBuilderComponent;
import com.caigou.component.HtmlHomePageBuilderComponent;
import com.caigou.enums.Constant;
import com.caigou.mapper.cms.ArticleKeywordMapper;
import com.caigou.mapper.cms.ArticleMapper;
import com.caigou.mapper.cms.ArticleTitleMapper;
import com.caigou.pojo.ArticleList;
import com.caigou.service.ChannelDataService;
import com.caigou.service.IEsArticleService;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.select.Elements;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class EsArticleLoadMq {
    @Resource
    private IEsArticleService esArticleService;
    @Resource
    private ArticleTitleMapper articleTitleMapper;// 文章标题列表mapper
    @Resource
    private ArticleKeywordMapper articleKeywordMapper;
    @Resource
    private ChannelDataService channelDataService;
    @Resource
    private HtmlDetailBuilderComponent htmlDetailBuilderComponent;// 模板生成组件(文章静态页)
    @Resource
    private HtmlHomePageBuilderComponent htmlHomePageBuilderComponent;// 模板生成组件(文章静态页)
    @Resource
    private ArticleMapper articleMapper;
    @Resource
    private AmqpTemplate amqpTemplate;
    @Value("${domain}")
    private String domain;


    @RabbitListener(queuesToDeclare = @Queue(Constant.CMS_ARTICLE_QUEUE))
    public synchronized void worker(List<EsArticleMqVO> message) {
        try {
            log.info("接收到的文章: " + message);
            //查询文章数据

            if (!CollectionUtils.isEmpty(message)) {
                List<String> ids = message.stream().map(EsArticleMqVO::getArticleId).distinct().collect(Collectors.toList());
                Map<String, String> articleIdOperateMap = message.stream().collect(Collectors.toMap(EsArticleMqVO::getArticleId, EsArticleMqVO::getOperate, (k1, k2) -> k1));


                List<Article> articleList = esArticleService.findArticleByArticleIds(ids);
                log.info("文章列表大小: " + articleList.size());
                if (!CollectionUtils.isEmpty(articleList)) {
                    List<String> articleIds = articleList.stream().map(Article::getArticleId).collect(Collectors.toList());
                    //批量查询文章内容页

                    Map<String, String> stringMap = new HashMap<>();
                    articleList.forEach(bean -> {
                        if (!StringUtils.isEmpty(bean.getArticleUrl())) {
                            Elements body = null;
                            try {
                                body = Jsoup.connect(bean.getArticleUrl()).get().body().getElementsByClass("container");
                                //将文章内容添加至文章字段
                                if (!CollectionUtils.isEmpty(body))
                                    body.forEach(element -> {
                                        String textContent = element.getElementById("main").text();
                                        stringMap.put(bean.getArticleId(), textContent);
                                    });

                            } catch (IOException e) {
                                e.printStackTrace();
                            }

                        }

                    });


                    //批量查询文章标题列表
                    List<ArticleTitle> titleByArticleIds = articleTitleMapper.findArticleTitleByArticleIds(articleIds);
                    Map<String, List<ArticleTitle>> articleTitleMap = titleByArticleIds.stream().collect(Collectors.groupingBy(ArticleTitle::getArticleId));
                    //批量查询文章关键词
                    String[] split = articleList.stream().map(Article::getArticleKeyWord).collect(Collectors.joining(",")).split(",");
                    List<String> articleKeyWordIds = Arrays.stream(split).distinct().collect(Collectors.toList());
                    List<ArticleKeyword> articleKeywords = articleKeywordMapper.findArticleKeywordsByArticleIds(articleKeyWordIds);

                    articleList.stream().map(bean -> {
                        EsArticle esArticle = new EsArticle();
                        BeanUtils.copyProperties(bean, esArticle);
                        esArticle.setArticleType(bean.getArticleType() != null ? bean.getArticleType().toString() : null);
                        esArticle.setArticlePromoter(Integer.parseInt(bean.getArticlePromoter()));
                        esArticle.setPublicTime(bean.getPublicTime() != null ? bean.getPublicTime() : bean.getCreateTime());
                        return esArticle;
                    }).peek(bean -> bean.setArticleKeyWordVOS(getKeyValueVOS(articleKeywords, bean.getArticleKeyWord())))
                            .peek(bean -> bean.setArticleTitleVOS(articleTitleMap.get(bean.getArticleId())))
                            .peek(bean -> bean.setArticlePureContent(stringMap.get(bean.getArticleId())))
                            .peek(bean -> {
                                //将内文标题与列表标题共同存入标题搜索字段中
                                String collectTitle = bean.getArticleTitleVOS().stream().map(ArticleTitle::getArticleTitle)
                                        .collect(Collectors.joining(",", bean.getArticleTitle() + ",", ""));
                                bean.setSearchTitle(collectTitle);
                            })
                            .forEach(bean -> {
                                if ("新增".equals(articleIdOperateMap.get(bean.getArticleId())) || "更新".equals(articleIdOperateMap.get(bean.getArticleId()))) {
                                    //增加
                                    EsArticle article = esArticleService.saveEsArticle(bean);
                                    Integer updateNum = esArticleService.updateArticleIndexStatus(article.getArticleId());

                                } else if ("删除".equals(articleIdOperateMap.get(bean.getArticleId()))) {
                                    //删除
                                    esArticleService.deleteEsArticle(bean);
                                }

                            });
                } else {
                    if (!CollectionUtils.isEmpty(message)) {
                        List<String> collect = message.stream().map(EsArticleMqVO::getArticleId).collect(Collectors.toList());
                        //需要删除的
                        collect.forEach(articleId->{
                            EsArticle esArticle = new EsArticle();
                            esArticle.setArticleId(articleId);
                            esArticleService.deleteEsArticle(esArticle);
                        });

                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    @RabbitListener(queuesToDeclare = @Queue(Constant.CMS_KEYWORD_QUEUE))
    public synchronized void updateArticleKeyword(Integer keywordId) {
        log.info("接收到文章关键词id={}", keywordId);
        //判断关键词是否存在
        ArticleKeyword articleKeyword = articleKeywordMapper.selectByPrimaryKey(keywordId);
        log.info("查询文章关键词信息={}", articleKeyword);
        //查询出所有使用到的关键词文章
        List<ArticleList> articles = articleMapper.findArticleByArticleKeyWord(keywordId.toString());
        //文章中删除关键词
        log.info("文章使用的数量={}", articles.size());
        if (!CollectionUtils.isEmpty(articles)) {
            articles.forEach(bean -> {
                log.info("打印文章id" + bean.getArticleId());

                if (articleKeyword == null) {
                    String keyWord = bean.getArticleKeyWord();
                    String[] split = keyWord.split(",");
                    if (split.length > 0) {
                        String str = Arrays.stream(split).filter(splitStr -> !splitStr.equals(keywordId.toString())).collect(Collectors.joining(","));
                        articleMapper.updateArticleKeyWord(bean.getArticleId(), str);
                        log.info("更新文章关键词成功={}", str);
                    }
                }
                // 获取当前文章除RSS频道以外发布的最早的记录--如果没有记录则更新RSS频道，如果有则更新最早的数据
                ChannelData channelData = channelDataService.loadLastChannelData(bean.getArticleId());
                log.info("查询频道数据={}", channelData);
                if (null == channelData) {
                    htmlDetailBuilderComponent.buildArticleHtml(bean.getArticleId(), "999");
                    log.info("channelData为空更新成功={}", channelData);
                } else {
                    htmlDetailBuilderComponent.buildArticleHtml(bean.getArticleId(), channelData.getPlateId());
                    log.info("channelData不为空更新成功={}", channelData);
                }
                // 更新全部相关联的静态资源
                List<ChannelData> channelDataList = channelDataService.loadLastChannelAllData(bean.getArticleId());
                if (null != channelDataList) {
                    log.info("更新全部相关联的静态资源");
                    channelDataList.forEach(item -> htmlHomePageBuilderComponent.buildHomePageHtml(item.getPlateId()));
                }
                log.info("发送mq消息更新文章索引");
                amqpTemplate.convertAndSend(Constant.CMS_ARTICLE_QUEUE, Collections.singletonList(new EsArticleMqVO(bean.getArticleId(), Constant.UPDATE_ARTICLE)));
            });

        }
        //存在则更新文章
        //查询文章keywordId是否含有
    }

    private List<KeyValueVO> getKeyValueVOS(List<ArticleKeyword> articleKeywords, String articleKeyWord) {
        if (CollectionUtils.isEmpty(articleKeywords) || StringUtils.isEmpty(articleKeyWord)) {
            return Collections.emptyList();
        }

        Map<Integer, String> articleKeywordMap = articleKeywords.stream().collect(Collectors.toMap(ArticleKeyword::getId, ArticleKeyword::getKeyword));
        String[] split = articleKeyWord.split(",");
        List<String> articleKeyWordIds = Arrays.asList(split);
        return articleKeyWordIds.stream().map(id -> {
            KeyValueVO valueVO = new KeyValueVO();
            valueVO.setValue(id);
            valueVO.setLabel(articleKeywordMap.get(Integer.parseInt(id)));
            valueVO.setDomain(domain);
            return valueVO;
        }).collect(Collectors.toList());
    }

}
